package csm.web.core;

import java.io.IOException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.velocity.VelocityContext;
import org.apache.velocity.context.Context;

import csm.common.Logger;
import csm.common.StringUtil;
import csm.web.core.sitemap.PathInfo;
import csm.web.core.sitemap.SiteMap;

/**
 * velocity 처리를 위한 가장 기본이 되는 서블릿 클래스
 * @author seungmun
 *
 */
public abstract class VelocityServletBase extends HttpServlet {

    /**	 */
	private static final long serialVersionUID = 3048349574753175180L;

	private PathInfo pathInfo;

	public PathInfo getPathInfo() {
		return pathInfo;
	}

	public void setPathInfo(PathInfo pathInfo) {
		this.pathInfo = pathInfo;
	}

	/**
     * @see HttpServlet#HttpServlet()
     */
    public VelocityServletBase() {
        super();
    }

    @Override
    public void init(ServletConfig config) throws ServletException {
    	super.init(config);
    }

	/**
	 * 루트 패스 경로를 리턴한다.
	 * @param request
	 * @return
	 */
	protected String getContextPath(HttpServletRequest request) {
		return !request.getContextPath().equals("/") ? request.getContextPath() + "/" : request.getContextPath();
	}
	/**
	 * 지정한 경로를 전체경로로 변환합니다
	 * @param request
	 * @param path
	 * @return
	 */
	protected String buildFullPath(HttpServletRequest request, String path) {

		String root = getContextPath(request);

		if (root.endsWith("/"))
			root = root.substring(0, root.length() - 1);

		if (path.startsWith("/"))
			path = path.substring(1);

		return root + "/" + path;
	}
	private String buildForwardPath(String path) {

		if (path.startsWith("/"))
			return path;

		return "/" + path;
	}
	/**
	 * 해당 페이지로 포워딩 해준다.
	 * @param context
	 * @param request
	 * @param response
	 * @param path
	 * @throws ServletException
	 * @throws IOException
	 */
	protected void forward(Context context, HttpServletRequest request, HttpServletResponse response, String path) throws ServletException, IOException {
		if (response.isCommitted())
			return;

		for (Object key : context.getKeys()) {
			request.setAttribute(key.toString(), context.get(key.toString()));
		}

		RequestDispatcher disp = request.getRequestDispatcher(buildForwardPath(path));
		try {
			disp.forward(request, response);

		} catch (org.apache.velocity.exception.ResourceNotFoundException e) {
			Logger.info(">>>>>>>>>>>>>> VelocityServletBase.forward(Context context, HttpServletRequest request, HttpServletResponse response, String path)");
			e.printStackTrace();
			response.sendError(500, e.getMessage());
		} catch (Exception e) {
			Logger.info(">>>>>>>>>>>>>> VelocityServletBase.forward(Context context, HttpServletRequest request, HttpServletResponse response, String path)");
			e.printStackTrace();
			response.sendError(500, e.getMessage());
		}
	}

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
	}

	/* (non-Javadoc)
	 * @see javax.servlet.http.HttpServlet#doPut(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
	 */
	@Override
	protected void doPut(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		super.doPut(req, resp);
	}

	/* (non-Javadoc)
	 * @see javax.servlet.http.HttpServlet#doDelete(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
	 */
	@Override
	protected void doDelete(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		super.doDelete(req, resp);
	}

	/* (non-Javadoc)
	 * @see javax.servlet.http.HttpServlet#service(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
	 */
	@Override
	protected void service(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		Context context = new VelocityContext();
		try {
			handleRequest(request, response, context);
		} catch (Exception e) {
			Logger.info(">>>>>>>>>>>>>> VelocityServletBase.service(HttpServletRequest request, HttpServletResponse response)");
			e.printStackTrace();
			response.sendError(500, e.getMessage());
		}
	}

	/* (non-Javadoc)
	 * @see javax.servlet.http.HttpServlet#service(javax.servlet.ServletRequest, javax.servlet.ServletResponse)
	 */
	@Override
	public void service(ServletRequest request, ServletResponse response)
			throws ServletException, IOException {
		super.service(request, response);
	}

	protected abstract void handleRequest(HttpServletRequest request, HttpServletResponse response, Context context) throws Exception;
	/**
	 * 풀패스 경로를 리턴한다.
	 * @param request
	 * @return
	 */
	protected String getRootFullPath(HttpServletRequest request) {
		String url = String.format("%s://%s%s%s",
				request.getScheme(),
				request.getLocalName().equalsIgnoreCase("0:0:0:0:0:0:0:1") ? "localhost" : request.getLocalName(),
				request.getLocalPort() == 80 || request.getLocalPort() == -1 || request.getLocalPort() == 443 ? "" : ":" + request.getLocalPort(),
				!request.getContextPath().equals("/") ? request.getContextPath() + "/" : request.getContextPath());
		return url;
	}
	/**
	 * Root를 제외한 요청 경로를 리턴한다.
	 * @param request
	 * @return
	 */
	protected String getRequestPath(HttpServletRequest request)
	{
		String rootPath = !request.getContextPath().equals("/") ? request.getContextPath() + "/" : request.getContextPath();
		return request.getRequestURI().replace(rootPath, "");
	}
	 /**
	  * Client IP 반환.
	  * @param request
	  * @return
	  */
	public String getClientIp(HttpServletRequest request) {
		String clientIp = request.getHeader("Proxy-Client-IP");
		if (clientIp == null) {
			clientIp = request.getHeader("WL-Proxy-Client-IP");
			if (clientIp == null) {
				clientIp = request.getHeader("X-Forwarded-For");
				if (clientIp == null) {
					clientIp = request.getRemoteAddr();
				}
			}
		}

		if( clientIp.equalsIgnoreCase("0:0:0:0:0:0:0:1"))
			clientIp = "localhost";
		return clientIp;
	}
	/**
	 * 현재 요청에 대한 결과를 렌더링할 페이지의 템플릿의 경로와 파일명을 가져옵니다.
	 * @param request
	 * @return
	 */
	public String getTemplateFile( HttpServletRequest request )
	{
		// URI를 분석해서, 템플릿을 가져온다.
		String tempateFile = getPathInfo().getTemplateFile();
		return tempateFile;
	}

	public String getThemaName(HttpServletRequest request)
	{
		String themaName = "thema/default";
		String tpl = request.getParameter("tpl");
		// tpl 파라메터는, 임시로 사용할때 사용하는 파라메터로, 이 파라메터가 존재하는 경우는 먼저 처리해 준다.
		// 테마미리보기에서 사용할 수 있을 것이다.

		if (StringUtil.isNullOrEmpty(tpl)) {
			// 현재 사용자의 테마를 가져와야 한다.
			tpl = SiteMap.getInstance().getCurrentThema();
			if (StringUtil.isNullOrEmpty(tpl)) {
				return themaName;
			}
		}
		return "thema/" + tpl;
	}
}
